/*
 * Copyright 2015 泛泛o0之辈
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.jfast.framework.plugin.wx.api.core;

import cn.jfast.framework.log.LogFactory;
import cn.jfast.framework.log.LogType;
import cn.jfast.framework.log.Logger;
import cn.jfast.framework.plugin.wx.api.constants.WxUrlConstant;
import cn.jfast.framework.plugin.wx.api.exception.WxRespException;
import cn.jfast.framework.plugin.wx.api.util.SimpleHttpReq;
import cn.jfast.framework.plugin.wx.api.vo.AuthInfo;
import cn.jfast.framework.plugin.wx.api.vo.WxInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;

/**
 * 微信开放平台API接口设计
 */
public class WxOpenApiHandler implements WxOpenApi {

    private static final Logger log = LogFactory.getLogger(LogType.Jfast,WxOpenApiHandler.class);

    private WxInfo wxInfo;

    private String ticket;

    /**
     * 微信开放平台接口构建
     *
     * @param wxInfo     服务组件公众号信息
     * @param ticket    允许凭证
     */
    public WxOpenApiHandler(WxInfo wxInfo, String ticket) {
        this.wxInfo = wxInfo;
        this.ticket = ticket;
    }

    public String getComponentToken() throws WxRespException {
        String token = wxInfo.getAccessToken();
        if (null == token
                || token.isEmpty()
                || wxInfo.getExpiresIn() < System.currentTimeMillis()) {
            synchronized (this){
                refreshComponentToken();
            }
            token = wxInfo.getAccessToken();
        }
        return token;
    }

    public void refreshComponentToken() throws WxRespException {
        String result = "";

        String data = "{" +
                "\"component_appid\":\"" + wxInfo.getAppId() + "\"," +
                "\"component_appsecret\":\"" + wxInfo.getAppSecert() + "\"," +
                "\"component_verify_ticket\":\"" + ticket + "\"" +
                "}";

        try {
            result = SimpleHttpReq.post(WxUrlConstant.COMPONENT_TOKEN_API,
                    SimpleHttpReq.APPLICATION_JSON,
                    data);
        } catch (IOException e) {
            log.error("刷新服务组件ACCESS_TOKEN时出现异常!!!");
            log.error(e.getLocalizedMessage(), e);
        }

        if (result.isEmpty()
                || result.contains("errcode")) {
            throw new WxRespException(result);
        }

        wxInfo.createAccessToken(result);
    }

    public void createPreauthcode() throws WxRespException {
        String url = String.format(WxUrlConstant.COMPONENT_API,
                "api_create_preauthcode", getComponentToken());
        String result = "";
        String data = "{" +
                "\"component_appid\":\"" + wxInfo.getAppId() + "\"" +
                "}";
        try {
            result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
        } catch (IOException e) {
            log.error("创建公众权预授权码时出现异常!!!");
            log.error(e.getLocalizedMessage(), e);
        }

        if (result.isEmpty()
                || result.contains("errcode")) {
            throw new WxRespException(result);
        }

        wxInfo.createPreAuthCode(result);
    }

    public String getPreauthcode() throws WxRespException {
        String auth_code = wxInfo.getPreAuthCode();
        if (null == auth_code
                || wxInfo.getPreAuthExpiresIn() < System.currentTimeMillis()){
            synchronized (this.wxInfo){
                createPreauthcode();
            }
        }
        return auth_code;
    }

    public AuthInfo queryAuth(String authCode) throws WxRespException {
        String url = String.format(WxUrlConstant.COMPONENT_API, "api_query_auth", getComponentToken());
        String result = "";
        String data = "{" +
                "\"component_appid\":\"" + wxInfo.getAppId() + "\" ," +
                "\" authorization_code\": \"" + authCode + "\"" +
                "}";
        try {
            result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
        } catch (IOException e) {
            log.error("换取授权公众号信息时出现异常!!!");
            log.error(e.getLocalizedMessage(), e);
        }

        if (result.isEmpty()
                || result.contains("errcode")) {
            throw new WxRespException(result);
        }

        AuthInfo tmp = JSON.parseObject(result, AuthInfo.class);
        return tmp;
    }

    public String getAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException {
        return null;
    }

    public void refreshAuthAccessToken(String authAppId, String authRefreshToken) throws WxRespException {

    }

    public AuthInfo getAuthorizerInfo(String authAppId) throws WxRespException {
        return null;
    }

    public String getAuthorizerOption(String authAppId, String optionName) throws WxRespException {
        String url = String.format(WxUrlConstant.COMPONENT_API, "api_get_authorizer_option", getComponentToken());
        String result = "";
        String data = "{" +
                "\"component_appid\":\""+ wxInfo.getAppId()+"\"," +
                "\"authorizer_appid\": \""+authAppId+"\"," +
                "\"option_name\": \""+optionName+"\"" +
                "}";
        try {
            result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
        } catch (IOException e) {
            log.error("获取授权公众号[%s]的选项值时出现异常!!!",authAppId);
            log.error(e.getLocalizedMessage(), e);
        }

        if (result.isEmpty()
                || result.contains("errcode")) {
            throw new WxRespException(result);
        }

        JSONObject tmp = JSON.parseObject(result);
        String optionValue = tmp.getString("option_value");
        if (log.isInfoEnable()) {
            String info = "获取授权公众号["+authAppId+"]";
            if(optionName.equals("location_report")){
                info += "地理位置上报选项成功,当前状态为: ";
                if (optionValue.equals("0")) {
                    info += "无上报";
                } else if (optionValue.equals("1")) {
                    info += "进入会话时上报";
                } else {
                    info += "每5s上报";
                }
            } else if(optionName.equals("voice_recognize")){
                info += "语音识别选项成功,当前状态为: ";
                info += (optionValue.equals("0")?"关闭":"开启");
            } else if(optionName.equals("customer_service")){
                info += "多客服选项成功,当前状态为: ";
                info += (optionValue.equals("0")?"关闭":"开启");
            }
            log.info("%s",info);
        }

        return result;
    }

    public void setAuthorizerOption(String authAppId, String optionName, String optionValue) throws WxRespException {
        String url = String.format(WxUrlConstant.COMPONENT_API, "api_set_authorizer_option", getComponentToken());
        String result = "";
        String data = "{" +
                "\"component_appid\":\""+ wxInfo.getAppId()+"\"," +
                "\"authorizer_appid\": \""+authAppId+"\"," +
                "\"option_name\": \""+optionName+"\"," +
                "\"option_value\":\""+optionValue+"\"" +
                "}";
        try {
            result = SimpleHttpReq.post(url, SimpleHttpReq.APPLICATION_JSON, data);
        } catch (IOException e) {
            log.error("设置授权公众号[%s]的选项值时出现异常!!!",authAppId);
            log.error(e.getLocalizedMessage(), e);
        }

        if (result.isEmpty()
                || !result.contains("ok")) {
            throw new WxRespException(result);
        }

        if (log.isInfoEnable()) {
            String info = "设置授权公众号["+authAppId+"]";
            if(optionName.equals("location_report")){
                info += "地理位置上报选项成功,当前状态为: ";
                if (optionValue.equals("0")) {
                    info += "无上报";
                } else if (optionValue.equals("1")) {
                    info += "进入会话时上报";
                } else {
                    info += "每5s上报";
                }
            } else if(optionName.equals("voice_recognize")){
                info += "语音识别选项成功,当前状态为: ";
                info += (optionValue.equals("0")?"关闭":"开启");
            } else if(optionName.equals("customer_service")){
                info += "多客服选项成功,当前状态为: ";
                info += (optionValue.equals("0")?"关闭":"开启");
            }
            log.info("%s",info);
        }
    }
}
